using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using Microsoft.CSharp;
using System.Linq;
using System.Text.RegularExpressions;
using System.Runtime.Serialization.Formatters.Binary;

namespace IGGCore
{
    /// <summary>
    /// The parser of online stats
    /// </summary>
    public class StatisticsParser : BaseParser
    {
        public static float AVG_PA = -1;
        public static float AVG_IP = -1;

        public void ParseStatistics(Scoreboard scoreboard)
        {
            string fileAverage = Path.Combine(CoreConstants.TEMP, "iggavgs.dat");
            BinaryFormatter binaryFormatter = new BinaryFormatter();

            int year = 2014;
            string[] urls = { "http://www.baseball-reference.com/leagues/MLB/%1-standard-batting.shtml".Replace("%1",year.ToString()), 
                              "http://www.baseball-reference.com/leagues/MLB/%1-standard-pitching.shtml".Replace("%1",year.ToString()), 
                              "http://www.baseball-reference.com/leagues/MLB/%1-standard-fielding.shtml".Replace("%1",year.ToString())};

            string[] filenames = {Path.Combine(CoreConstants.TEMP, urls[0].Substring(urls[0].Length - 20)),
                                  Path.Combine(CoreConstants.TEMP, urls[1].Substring(urls[1].Length - 20)),
                                  Path.Combine(CoreConstants.TEMP, urls[2].Substring(urls[2].Length - 20))};

            FileStream stream = null;

            // BATTING STATS
            // only update if the day is more than one day later... or a day later AND later than 11am

            if (File.Exists(filenames[0]) 
                && ((File.GetLastWriteTime(filenames[0]).DayOfYear == DateTime.Now.DayOfYear)&& (DateTime.Now.Hour < 11))
                || ((File.GetLastWriteTime(filenames[0]).DayOfYear == DateTime.Now.DayOfYear) && (File.GetLastWriteTime(filenames[0]).Hour >= 11)))
            {
                stream = new FileStream(filenames[0], FileMode.Open);
                scoreboard.StatsBatting = (List<Dictionary<string, object>>)binaryFormatter.Deserialize(stream);

                // LOAD THE AVGS
                if (File.Exists(fileAverage))
                {
                    StreamReader reader = new StreamReader(fileAverage);
                    AVG_PA = float.Parse(reader.ReadLine());
                    AVG_IP = float.Parse(reader.ReadLine());
                    reader.Close();
                }
                stream.Close();
            }
            else
            {
                scoreboard.StatsBatting = ExtractStats(urls[0]);
                stream = new FileStream(filenames[0], FileMode.Create);
                binaryFormatter.Serialize(stream, scoreboard.StatsBatting);
                stream.Close();
            }

            // PITCHING
            if (File.Exists(filenames[1])
                && ((File.GetLastWriteTime(filenames[1]).DayOfYear == DateTime.Now.DayOfYear) && (DateTime.Now.Hour < 11))
                || ((File.GetLastWriteTime(filenames[1]).DayOfYear == DateTime.Now.DayOfYear) && (File.GetLastWriteTime(filenames[1]).Hour >= 11)))
 
            {
                 stream = new FileStream(filenames[1], FileMode.Open);
                scoreboard.StatsPitching = (List<Dictionary<string, object>>)binaryFormatter.Deserialize(stream);
                stream.Close();
            }
            else
            {
                scoreboard.StatsPitching = ExtractStats(urls[1]);
                 stream = new FileStream(filenames[1], FileMode.Create);
                binaryFormatter.Serialize(stream, scoreboard.StatsPitching);
                stream.Close();
            }

            // FIELDING
            if (File.Exists(filenames[2])
                && ((File.GetLastWriteTime(filenames[2]).DayOfYear == DateTime.Now.DayOfYear) && (DateTime.Now.Hour < 11))
                || ((File.GetLastWriteTime(filenames[2]).DayOfYear == DateTime.Now.DayOfYear) && (File.GetLastWriteTime(filenames[2]).Hour >= 11)))
            {
                 stream = new FileStream(filenames[2], FileMode.Open);
                scoreboard.StatsFielding = (List<Dictionary<string, object>>)binaryFormatter.Deserialize(stream);
                stream.Close();
            }
            else
            {
                scoreboard.StatsFielding = ExtractStats(urls[2]);
                 stream = new FileStream(filenames[2], FileMode.Create);
                binaryFormatter.Serialize(stream, scoreboard.StatsFielding);
                stream.Close();
            }

            // SAVE THE AVERAGES!
            StreamWriter writer = new StreamWriter(fileAverage);
            writer.WriteLine(AVG_PA);
            writer.WriteLine(AVG_IP);
            writer.Close();

            // TEAMS STATS

        }

        private List<Dictionary<string, object>> ExtractStats(string url)
        {
            float PATotal = 0;
            float PACount = 0;

            float IPTotal = 0;
            float IPCount = 0;

            List<string> categories = new List<string>();
            List<Dictionary<string, object>> stats = new List<Dictionary<string, object>>();

            string transContent = "";
            StreamReader reader = null;
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                reader = new StreamReader(request.GetResponse().GetResponseStream());
                transContent = reader.ReadToEnd();
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }
            }

            transContent = transContent.Substring(transContent.IndexOf("<table class=\"sortable  stats_table\" id=\"players_standard"));
            string headers = transContent.Substring(transContent.IndexOf("<thead>"), transContent.IndexOf("</thead>") - transContent.IndexOf("<thead>"));
            headers = headers.Substring(headers.IndexOf("<th"));
            string[] headersArray = headers.Split(new string[] { "</th>" }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string header in headersArray)
            {
                string category = ExtractCategory(header);
                if (category != "\n")
                {
                    categories.Add(category);
                }
            }

            transContent = transContent.Substring(transContent.IndexOf("<tbody>") + 7);
            string[] playersArray = transContent.Split(new string[] { "</tr>" }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string playstr in playersArray)
            {
                Dictionary<string, object> play = ExtractPlayer(playstr, categories);
                if (play.Keys.Count > 0 && play["Rk"].ToString() != "" && play["Tm"].ToString() != "0")
                {
                    stats.Add(play);
                    if (play.ContainsKey("PA"))
                    {
                        PACount++;
                        PATotal += (float)play["PA"];
                    }
                    else if (play.ContainsKey("IP"))
                    {
                        IPCount++;
                        IPTotal += (float)play["IP"];
                    }
                }
            }
            if (PATotal > 0)
            {
                AVG_PA = (float)PATotal / (float)PACount;
            }
            if (IPTotal > 0)
            {
                AVG_IP = (float)IPTotal / (float)IPCount;
                AVG_IP = AVG_IP + (AVG_IP * 0.2F);
            }

            return stats;
        }



        private string ExtractCategory(string line)
        {
            string result = line.Replace("<nobr>","");
            result = result.Replace("</nobr>", "");
            result = result.Substring(result.LastIndexOf(">") + 1);
            if (result == "")
            {
                result = "Player";
            }
            return result.Replace("&nbsp;"," ");
        }

        private Dictionary<string, object> ExtractPlayer(string line, List<string> categories)
        {
            string temp = "";
            string[] playertd = null;
            Dictionary<string, object> player = new Dictionary<string, object>();
            try
            {
                line = line.Substring(line.IndexOf("<td"));
                playertd = line.Split(new string[] { "</td>" }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < categories.Count; i++ )
                {
                    int len = 3;
                    int idx = playertd[i].LastIndexOf("\" >" );
                    if (idx <0 )
                    {
                        idx = playertd[i].LastIndexOf("\">");
                        len = 2;
                    }
                    temp = playertd[i].Substring(idx + len).Replace("</a>","");
                    idx = temp.LastIndexOf(">");
                    if (idx >-1)
                    {
                        temp = temp.Substring(idx + 1);
                    }

                    temp = temp.Replace("&nbsp;", " ");
                    temp = temp.Replace("*", "");
                    temp = temp.Replace("#", "");
                    if (Regex.IsMatch(temp, @"^\d+$"))
                    {
                        player.Add(categories[i], float.Parse(temp));
                    }
                    else if (temp.Trim().StartsWith(".") || temp.Trim().StartsWith("1."))
                    {
                        player.Add(categories[i], float.Parse(temp));
                    }
                    else if (temp.Trim() == string.Empty)
                    {
                        player.Add(categories[i], 0F);
                    }
                    else if (temp.StartsWith("--"))
                    {
                        player.Add(categories[i], 25F);
                    }
                    else if (temp.StartsWith("-"))
                    {
                        player.Add(categories[i], float.Parse(temp));
                    }
                    else
                    {
                        try
                        {
                            player.Add(categories[i], float.Parse(temp));
                        }
                        catch
                        {
                            player.Add(categories[i], temp);
                        }
                        
                    }
                    
                }
            }
            catch(Exception ex)
            {

            }

            return player;
        }

 

    }
}
